package com.burst.reptile.modular.system.service.impl;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.burst.reptile.common.constant.UserConstants;
import com.burst.reptile.common.exception.CustomException;
import com.burst.reptile.common.utils.ToolUtil;
import com.burst.reptile.framework.aspectj.DataScopeAspect;
import com.burst.reptile.framework.aspectj.lang.annotation.DataScope;
import com.burst.reptile.modular.system.entity.SysRole;
import com.burst.reptile.modular.system.entity.SysRoleDept;
import com.burst.reptile.modular.system.entity.SysRoleMenu;
import com.burst.reptile.modular.system.entity.SysUserRole;
import com.burst.reptile.modular.system.mapper.SysRoleDeptMapper;
import com.burst.reptile.modular.system.mapper.SysRoleMapper;
import com.burst.reptile.modular.system.mapper.SysRoleMenuMapper;
import com.burst.reptile.modular.system.mapper.SysUserRoleMapper;
import com.burst.reptile.modular.system.service.ISysRoleService;

import lombok.RequiredArgsConstructor;

/**
 * <p>
 * 角色信息表 服务实现类
 * </p>
 *
 * @author wujin
 * @since 2020-05-22
 */
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> implements ISysRoleService {

	private final SysRoleMenuMapper roleMenuMapper;

	private final SysRoleDeptMapper roleDeptMapper;
	
	private final SysUserRoleMapper userRoleMapper;

	/**
	 * 根据用户ID查询权限
	 */
	@Override
	public Set<String> selectRolePermissionByUserId(Long userId) {
		List<SysRole> perms = this.baseMapper.selectRolePermissionByUserId(userId);
		Set<String> permsSet = new HashSet<>();
		for (SysRole perm : perms) {
			if (ToolUtil.isNotEmpty(perm)) {
				permsSet.addAll(Arrays.asList(perm.getRoleKey().trim().split(",")));
			}
		}
		return permsSet;
	}

	@Override
	@DataScope(deptAlias = "d")
	public List<SysRole> selectRoleAll(SysRole role) {
		return this.baseMapper.selectRoleAll(role);
	}

	@Override
	public List<Integer> selectRoleListByUserId(Long userId) {
		return this.baseMapper.selectRoleListByUserId(userId);
	}

	@Override
	@DataScope(deptAlias = "d")
	public Page<SysRole> selectRoleList(Page<SysRole> page, SysRole role) {
		return this.baseMapper.selectRoleList(page, role);
	}

	@Override
	public String checkRoleNameUnique(SysRole role) {
		Long roleId = ToolUtil.isEmpty(role.getRoleId()) ? -1L : role.getRoleId();
		SysRole info = this.baseMapper.selectOne(new QueryWrapper<SysRole>().eq("role_name", role.getRoleName()));
		if (ToolUtil.isNotEmpty(info) && info.getRoleId().longValue() != roleId.longValue()) {
			return UserConstants.NOT_UNIQUE;
		}
		return UserConstants.UNIQUE;
	}

	@Override
	public String checkRoleKeyUnique(SysRole role) {
		Long roleId = ToolUtil.isEmpty(role.getRoleId()) ? -1L : role.getRoleId();
		SysRole info = this.baseMapper.selectOne(new QueryWrapper<SysRole>().eq("role_key", role.getRoleKey()));
		if (ToolUtil.isNotEmpty(info) && info.getRoleId().longValue() != roleId.longValue()) {
			return UserConstants.NOT_UNIQUE;
		}
		return UserConstants.UNIQUE;
	}

	@Override
	@Transactional
	public int insertRole(SysRole role) {
		role.setDataScope(DataScopeAspect.DATA_SCOPE_CUSTOM);
		this.baseMapper.insert(role);
		return insertRoleMenu(role);
	}

	@Override
	public void checkRoleAllowed(SysRole role) {
		if (ToolUtil.isNotEmpty(role.getRoleId()) && role.isAdmin()) {
			throw new CustomException("不允许操作超级管理员角色");
		}

	}

	@Override
	@Transactional
	public int updateRole(SysRole role) {
		// 修改角色信息
		this.baseMapper.updateById(role);
		// 删除角色与菜单关联
		roleMenuMapper.delete(new QueryWrapper<SysRoleMenu>().eq("role_id", role.getRoleId()));
		return insertRoleMenu(role);
	}

	/**
	 * 新增角色菜单信息
	 * 
	 * @param role 角色对象
	 */
	public int insertRoleMenu(SysRole role) {
		int rows = 1;
		// 新增用户与角色管理
		List<SysRoleMenu> list = new ArrayList<SysRoleMenu>();
		for (Long menuId : role.getMenuIds()) {
			SysRoleMenu rm = new SysRoleMenu();
			rm.setRoleId(role.getRoleId());
			rm.setMenuId(menuId);
			list.add(rm);
		}
		if (list.size() > 0) {
			rows = roleMenuMapper.batchRoleMenu(list);
		}
		return rows;
	}

	@Override
	@Transactional
	public int authDataScope(SysRole role) {
		// 修改角色信息
		this.baseMapper.updateById(role);
		// 删除角色与部门关联
		roleDeptMapper.delete(new QueryWrapper<SysRoleDept>().eq("role_id", role.getRoleId()));
		// 新增角色和部门信息（数据权限）
		return insertRoleDept(role);
	}

	@Override
	public int updateRoleStatus(SysRole role) {
		return this.baseMapper.updateById(role);
	}

	@Override
	public int deleteRoleByIds(Long[] roleIds) {
		for (Long roleId : roleIds) {
			SysRole sysRole = new SysRole();
			sysRole.setRoleId(roleId);
			checkRoleAllowed(sysRole);
			SysRole role = selectRoleById(roleId);
			if (countUserRoleByRoleId(roleId) > 0) {
				throw new CustomException(String.format("%1$s已分配,不能删除", role.getRoleName()));
			}
		}
		return this.baseMapper.deleteRoleByIds(roleIds);
	}

	/**
	 * 新增角色部门信息(数据权限)
	 *
	 * @param role 角色对象
	 */
	public int insertRoleDept(SysRole role) {
		int rows = 1;
		// 新增角色与部门（数据权限）管理
		List<SysRoleDept> list = new ArrayList<SysRoleDept>();
		for (Long deptId : role.getDeptIds()) {
			SysRoleDept rd = new SysRoleDept();
			rd.setRoleId(role.getRoleId());
			rd.setDeptId(deptId);
			list.add(rd);
		}
		if (list.size() > 0) {
			rows = roleDeptMapper.batchRoleDept(list);
		}
		return rows;
	}

	/**
	 * 通过角色ID查询角色
	 * 
	 * @param roleId 角色ID
	 * @return 角色对象信息
	 */
	public SysRole selectRoleById(Long roleId) {
		return this.baseMapper.selectById(roleId);
	}

	@Override
	public int countUserRoleByRoleId(Long roleId) {
		return userRoleMapper.selectCount(new QueryWrapper<SysUserRole>().eq("role_id", roleId));
	}

	@Override
	@DataScope(deptAlias = "d")
	public List<SysRole> selectRoleListExport(SysRole role) {
		return this.baseMapper.selectRoleListExport(role);
	}

}
